package show.marvelous.domain.chessgame.service;

import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import show.marvelous.domain.chessgame.aggregate.ChessGame;
import show.marvelous.domain.chessgame.aggregate.entity.DiceRecord;
import show.marvelous.domain.chessgame.aggregate.entity.MoveEvent;
import show.marvelous.domain.chessgame.aggregate.entity.PlayRecord;
import show.marvelous.domain.chessgame.constans.PieceCodeEnum;
import show.marvelous.domain.chessgame.repository.ChessGameRepository;
import show.marvelous.domain.chessgame.repository.DiceRecordRepository;
import show.marvelous.domain.chessgame.repository.MoveEventRepository;
import show.marvelous.domain.chessgame.repository.PlayRecordRepository;

/**
 * The type Chess game service.
 * @author Kris 2021/8/17
 */
@Service("chessGameServiceImpl")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ChessGameServiceImpl implements IChessGameService{

    private final PlayRecordRepository playRecordRepository;
    private final MoveEventRepository moveEventRepository;
    private final Map<Long,ChessGame> games;
    private final ChessGameRepository chessGameRepository;
    private final DiceRecordRepository diceRecordRepository;

    @Override
    public Integer shakeDice(long gameId){
        ChessGame game = loadGame(gameId);
        DiceRecord diceRecord = game.shakeDice();
        diceRecordRepository.save(gameId, diceRecord);
        return diceRecord.getStep();
    }

    /**
     * Move.
     *
     */
    @Override
    public void move(long gameId, PieceCodeEnum code){
        ChessGame game = loadGame(gameId);
        PlayRecord playRecord = game.buildPlayRecord(code);
        playRecordRepository.save(gameId, playRecord);
        Optional<MoveEvent> moveEvents = game.play(playRecord);
        moveEvents.ifPresent(e -> executeMoveEvent(game, e));
    }

    @Override
    public ChessGame initNewGame(){
        return chessGameRepository.initNewGame();
    }

    @Override
    public ChessGame loadGame(Long gameId){
        ChessGame chessGame = games.get(gameId);
        if(chessGame != null){
            return chessGame;
        }
        Optional<ChessGame> chessGameOptional = chessGameRepository.loadGame(gameId);
        if(!chessGameOptional.isPresent()){
            throw new IllegalArgumentException("找不到游戏信息");
        }
        games.put(gameId, chessGameOptional.get());
        return chessGameOptional.get();
    }

    private void executeMoveEvent(ChessGame game, MoveEvent moveEvent){
        // 1. 保存移动事件
        moveEventRepository.save(game.getId(), moveEvent);
        // 2. 执行移动事件
        Collection<MoveEvent> moveEvents = game.happen(moveEvent);
        // 3. 处理新的事件
        moveEvents.forEach(e -> executeMoveEvent(game, e));
    }
}
